# coding:utf-8
# writingtime: 2020-8-4
# reference: https://doi.org/10.1007/s40815-021-01243-2

from DistanceFunction.euclidean import Euclidean
from math import log


class FM:
    def __init__(self, dataList, membershipMatrix, clusterCenter, a):
        """
        function
        :param dataList: 样本向量
        :param membershipMatrix: 关系矩阵
        :param clusterCenter: 聚合中心
        :param a: 参数
        """
        self.dataList = dataList
        self.membershipMatrix = membershipMatrix
        self.clusterCenter = clusterCenter
        self.a = a

    def getalpha(self):
        """
        function: 计算alpha_f的值
        :return:
        """
        sum1 = 0
        for i in range(len(self.clusterCenter)):
            for j in range(len(self.dataList)):
                sum1 += ((self.membershipMatrix[i][j] - 1 / len(self.clusterCenter)) ** 2) * (
                        Euclidean.getresult(self.dataList[j], self.clusterCenter[i]) ** 2)
        li_temp = []
        for i in range(len(self.clusterCenter)):
            for k in range(len(self.clusterCenter)):
                if i != k:
                    li_temp.append(Euclidean.getresult(self.clusterCenter[i], self.clusterCenter[k]) ** 2)
        minvalue = min(li_temp) / len(self.dataList)
        value = sum1 / minvalue
        return value

    def getfm(self):
        """
        function: 计算FM的评价函数
        :return:
        """
        sum1 = 0
        for i in range(len(self.clusterCenter)):
            for j in range(len(self.dataList)):
                sum1 += self.membershipMatrix[i][j] * log(self.membershipMatrix[i][j], self.a)
        value = self.getalpha() * (-sum1)
        return value

    @staticmethod
    def getresult(dataList, membershipMatrix, clusterCenter, m=2, a=2):
        """
        function: fm评价函数
        :param dataList: 样本向量
        :param membershipMatrix: 评价矩阵
        :param clusterCenter: 中心点向量
        :param m: 聚合方程参数
        :param a: 评价函数参数
        :return: FM评价值
        """
        return FM(dataList, membershipMatrix, clusterCenter, a).getfm()
